package com.baidu.encrypt.service.impl;

import com.baidu.encrypt.common.utils.SM3Util;
import com.baidu.encrypt.common.utils.SM4Util;
import com.baidu.encrypt.entity.ModelServiceInfo;
import com.baidu.encrypt.entity.SampleInfo;
import com.baidu.encrypt.mapper.ModelServiceInfoMapper;
import com.baidu.encrypt.mapper.SampleInfoMapper;
import com.baidu.encrypt.service.ModelServiceInfoService;
import com.baidu.encrypt.service.SampleInfoService;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.Date;
import java.util.StringJoiner;

@Service
public class ModelServiceInfoServiceImpl extends ServiceImpl<ModelServiceInfoMapper, ModelServiceInfo> implements ModelServiceInfoService {
    @Autowired
    private SM4Util sm4Util;

    @Override
    public <E extends IPage<ModelServiceInfo>> E page(E page, Wrapper<ModelServiceInfo> queryWrapper) {
        E result = super.page(page, queryWrapper);
        result.getRecords().forEach(this::decryptEntity); // 只解密，不做篡改校验
        return result;
    }


    @Override
    public boolean save(ModelServiceInfo entity) {
        encryptEntity(entity);
        return super.save(entity);
    }

    @Override
    public boolean updateById(ModelServiceInfo entity) {

        //        String userId = UserContext.getUserId();
        String userId = "xiaofei";
        if (userId != null) {
            entity.setUpdatedBy(userId);
        }
        entity.setUpdatedTime(new Date());

        ModelServiceInfo byId = getById(entity.getId());
        byId.setCreatedBy(entity.getCreatedBy() == null ? byId.getCreatedBy() : entity.getCreatedBy());
        byId.setUpdatedBy(entity.getUpdatedBy() == null ? byId.getUpdatedBy() : entity.getUpdatedBy());
        byId.setName(entity.getName() == null ? byId.getName() : entity.getName());
        byId.setCode(entity.getCode() == null ? byId.getCode() : entity.getCode());
        byId.setStartStopStatus(entity.getStartStopStatus() == null ? byId.getStartStopStatus() : entity.getStartStopStatus());
        byId.setSource(entity.getSource() == null ? byId.getSource() : entity.getSource());
        byId.setModelId(entity.getModelId() == null ? byId.getModelId() : entity.getModelId());
        byId.setProjectId(entity.getProjectId() == null ? byId.getModelId() : entity.getProjectId());

        encryptEntity(byId);
        return super.updateById(byId);
    }

    @Override
    public ModelServiceInfo getById(Serializable id) {
        ModelServiceInfo entity = super.getById(id);
        if (entity != null) {
            decryptEntity(entity);
            verifyIntegrity(entity);
        }
        return entity;
    }

    /**
     * 加密（存库前）
     */
    private void encryptEntity(ModelServiceInfo modelServiceInfo) {
        try {
            // 先用明文计算 SM3
            String sm3Plain = buildPlainString(modelServiceInfo);
            modelServiceInfo.setSm3(SM3Util.encrypt(sm3Plain));

            // 对每个字段加密（空值不加密，直接存 null）
            modelServiceInfo.setName(encryptNullable(modelServiceInfo.getName()));
            modelServiceInfo.setSource(encryptNullable(modelServiceInfo.getSource()));
            modelServiceInfo.setCode(encryptNullable(modelServiceInfo.getCode()));
            modelServiceInfo.setStartStopStatus(encryptNullable(modelServiceInfo.getStartStopStatus()));
            modelServiceInfo.setCreatedBy(encryptNullable(modelServiceInfo.getCreatedBy()));
            modelServiceInfo.setUpdatedBy(encryptNullable(modelServiceInfo.getUpdatedBy()));
        } catch (Exception e) {
            throw new RuntimeException("加密失败", e);
        }
    }

    /**
     * 解密（查库后）
     */
    private void decryptEntity(ModelServiceInfo modelServiceInfo) {
        try {
            modelServiceInfo.setName(decryptNullable(modelServiceInfo.getName()));
            modelServiceInfo.setSource(decryptNullable(modelServiceInfo.getSource()));
            modelServiceInfo.setCode(decryptNullable(modelServiceInfo.getCode()));
            modelServiceInfo.setStartStopStatus(decryptNullable(modelServiceInfo.getStartStopStatus()));
            modelServiceInfo.setCreatedBy(decryptNullable(modelServiceInfo.getCreatedBy()));
            modelServiceInfo.setUpdatedBy(decryptNullable(modelServiceInfo.getUpdatedBy()));
        } catch (Exception e) {
            throw new RuntimeException("解密失败", e);
        }
    }

    /**
     * 防篡改校验
     */
    private void verifyIntegrity(ModelServiceInfo modelServiceInfo) {
        String sm3New = SM3Util.encrypt(buildPlainString(modelServiceInfo));
        if (!sm3New.equals(modelServiceInfo.getSm3())) {
            throw new SecurityException("数据已被篡改！");
        }
    }

    /**
     * 构建明文串（SM3用，null 统一转 ""）
     */
    private String buildPlainString(ModelServiceInfo s) {
        return new StringJoiner("|")
                .add(nullToEmpty(s.getName()))
                .add(nullToEmpty(s.getCode()))
                .add(nullToEmpty(s.getStartStopStatus()))
                .add(nullToEmpty(s.getSource()))
                .add(nullToEmpty(s.getCreatedBy()))
                .add(nullToEmpty(s.getUpdatedBy()))
                .add(nullToEmpty(s.getProjectId()))
                .toString();
    }

    /**
     * 工具方法：null → ""
     */
    private String nullToEmpty(String str) {
        return str == null ? "" : str;
    }

    /**
     * 工具方法：加密 null 安全
     */
    private String encryptNullable(String value) throws Exception {
        return value == null ? null : sm4Util.encrypt(value);
    }

    /**
     * 工具方法：解密 null 安全
     */
    private String decryptNullable(String value) throws Exception {
        return value == null ? null : sm4Util.decrypt(value);
    }

}
